package com.xquant.marketdata.marketdata.service.impl;


import com.xquant.common.redis.service.RedisService;
import com.xquant.marketdata.common.utils.StringUtils;
import com.xquant.marketdata.common.utils.UnderlyingUtils;
import com.xquant.common.core.domain.Underlying;
import com.xquant.marketdata.marketdata.mapper.InstrumentMapper;
import com.xquant.marketdata.marketdata.service.InstrumentService;
import org.apache.commons.collections.MapUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.PostConstruct;
import java.math.BigDecimal;
import java.util.*;
import java.util.concurrent.*;
import java.util.stream.Collectors;

/**
 * @Auther: B946
 * @Date: 23/12/2019 10:17
 * @Description:
 */
@Service
@Transactional
public class InstrumentServiceImpl implements InstrumentService {

    @Autowired
    private InstrumentMapper instrumentMapper;
    @Autowired
    private RedisTemplate redisTemplate;
    ExecutorService fixedThreadPool = Executors.newCachedThreadPool();
    ScheduledExecutorService scheduledExecutorService = Executors.newSingleThreadScheduledExecutor();
    //时间间隔(一天)
    private static final long PERIOD_DAY = 24 * 60 * 60 * 1000;
    //时间间隔(六小时)
    private static final long PERIOD_SIX = 6 * 60 * 60 * 1000;
    //时间间隔(三小时)
    private static final long PERIOD_THREE = 3 * 60 * 60 * 1000;
    //时间间隔(一小时)
    private static final long PERIOD_ONE = 1 * 60 * 60 * 1000;
    @Autowired
    private RedisService redisService;


    /**
     * 项目启动时，初始化到缓存
     */
    @PostConstruct
    public void init() {
        Map map = new HashMap();
        Integer count = instrumentMapper.selectUnderlyingDatasCount(map);
        Runnable runnable = new Runnable() {
            public void run() {
                try {
                    Thread.sleep(3 * 1000);
                    long startTime = System.currentTimeMillis();
                    int cs = (int) Math.ceil(BigDecimal.valueOf(count).divide(BigDecimal.valueOf(10000)).doubleValue());
                    List<Callable<List<Underlying>>> tasks = new ArrayList<Callable<List<Underlying>>>();//添加任务

                    for (int i = 0; i < cs; i++) {
                        int start = i * 10000;
                        int end = (i + 1) * 10000 + 1;
                        map.put("start", String.valueOf(start));
                        map.put("end", String.valueOf(end));
                        Callable<List<Underlying>> qfe = new InstrumentRedisThread(instrumentMapper, redisTemplate, null, start, end);
                        tasks.add(qfe);
                    }
                    //定义固定长度的线程池  防止线程过多
                    ExecutorService execservice = Executors.newFixedThreadPool(5);
                    List<Future<List<Underlying>>> futures = execservice.invokeAll(tasks);
                    // 处理线程返回结果
                    if (futures != null && futures.size() > 0) {
                        for (Future<List<Underlying>> future : futures) {
                            try {
                                future.get();
                            } catch (ExecutionException e) {
                                e.printStackTrace();
                            }
                        }
                    }
                    execservice.shutdown();  // 关闭线程池
                    long endTime = System.currentTimeMillis();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        };

        int initDelay = 0;

        // 第二个参数为首次执行的延时时间，第三个参数为定时执行的间隔时间
        scheduledExecutorService.scheduleAtFixedRate(runnable, initDelay, PERIOD_DAY, TimeUnit.MILLISECONDS);

    }

    @Override
    public List<Underlying> selectUnderlyingDatas(Map<String, Object> params) {
        if (StringUtils.isEmpty(MapUtils.getString(params, "condition"))) {
            params.put("condition", "");
        }
        /*
        * 根据前台代码判断是否过滤已经过期的标的
        * */
        String condition = MapUtils.getString(params, "condition").toUpperCase();
        String aType = MapUtils.getString(params, "aType");
        String filterDate = MapUtils.getString(params, "filterDate");
        if (StringUtils.isNotEmpty(filterDate)) {
            List<Underlying> dictDatas = UnderlyingUtils.getDimCacheFilterDate(condition, aType,filterDate);
            if (StringUtils.isEmpty(MapUtils.getString(params, "iName"))&&StringUtils.isNotNull(dictDatas) && dictDatas.size() > 0) {
                return dictDatas;
            }
        }
        List<Underlying> dictDatas = UnderlyingUtils.getDimCache(condition, aType);
        if (StringUtils.isEmpty(MapUtils.getString(params, "iName"))&&StringUtils.isNotNull(dictDatas) && dictDatas.size() > 0) {
            return dictDatas;
        }
        params.put("start", String.valueOf(0));
        params.put("end", String.valueOf(15));

        List<Underlying> paramDatas = instrumentMapper.selectUnderlyingDatas(params);
        //List<Underlying> paramDatas = instrumentMapper.selectUnderlyingDatasByRedis(params);
        if (StringUtils.isNotNull(paramDatas)) {
            return paramDatas;
        }
        return null;
    }

    @Override
    public List<Map<String, Object>> getInstruments(Map<String, Object> params) {
        //java去重
        List<Map<String, Object>> collect = instrumentMapper.getInstruments(params).stream().distinct().collect(Collectors.toList());
        return collect;
    }


    @Override
    public List<Map<String, Object>> getAllInstrument() {
        return instrumentMapper.getAllInstrument();
    }

    @Override
    public List<Map<String, Object>> getInstrumentsBySubject(Map<String, Object> params) {
        //java去重
        List<Map<String, Object>> collect = instrumentMapper.getInstrumentsBySubject(params).stream().distinct().collect(Collectors.toList());
        return collect;
    }

    @Override
    public List<Map<String, Object>> getInstruments2(Map<String, Object> params) {
        //java去重
        List<Map<String, Object>> collect = instrumentMapper.getInstruments2(params).stream().distinct().collect(Collectors.toList());
        return collect;
    }

    @Override
    public List<Map<String, Object>> getIrs(Map<String, Object> params) {

        return instrumentMapper.getIrs(params);
    }

    @Override
    public List<Map<String, Object>> getBondFutures(Map<String, Object> params) {

        return instrumentMapper.getBondFutures(params);
    }

    @Override
    public List<Map<String, Object>> getBondFutureCtds(Map<String, Object> params) {
        return instrumentMapper.getBondFutureCtds(params);
    }

    @Override
    public List<Map<String, Object>> getBonds(Map<String, Object> params) {
        return instrumentMapper.getBonds(params);
    }

    @Override
    public List<Map<String, Object>> getCrmws(Map<String, Object> params) {
        return instrumentMapper.getCrmws(params);
    }

    @Override
    public List<Map<String, Object>> getFx(Map<String, Object> params) {
        return instrumentMapper.getFx(params);
    }
}
